import numpy as np
import matplotlib.pyplot as plt


class BinomialOptionPricing:
    def __init__(self, S, K, r, T, sigma, n):
        self.S = S
        self.K = K
        self.r = r
        self.T = T
        self.sigma = sigma
        self.n = n

    def calculate_price(self):
        delta_t = self.T / self.n
        u = np.exp(self.sigma * np.sqrt(delta_t))
        d = 1 / u
        p = (np.exp(self.r * delta_t) - d) / (u - d)

        price_tree = np.zeros((self.n + 1, self.n + 1))
        option_tree = np.zeros((self.n + 1, self.n + 1))

        for i in range(self.n + 1):
            for j in range(i + 1):
                price_tree[i, j] = self.S * (u ** (i - j)) * (d ** j)
                option_tree[i, j] = max(price_tree[i, j] - self.K, 0)

        for i in range(self.n - 1, -1, -1):
            for j in range(i + 1):
                option_tree[i, j] = (p * option_tree[i + 1, j] + (1 - p) * option_tree[i + 1, j + 1]) * np.exp(
                    -self.r * delta_t)

        return option_tree[0, 0]


if __name__ == '__main__':
    divdend = 0.44 / 100.0
    S = 218.36  # Current price of the underlying asset
    K = 220  # Strike price
    r = 4.62 / 100.0  # Risk-free interest rate
    T = 14.0 / 365.0  # Time to expiration
    sigma = 36.23 / 100.0  # Volatility

    n = 100  # Number of time steps

    binomial_model = BinomialOptionPricing(S, K, r, T, sigma, n)
    put_price = binomial_model.calculate_price()
    print("Put Option Price:", put_price)
